需求:
在profit(收益)表中包含一列 ‘rate(费率)’为百分比,数据类型为varchar,插入的数据为百分数(即xx.xx%)。要求按照百分比的大小排序,数据库为oracle。
分析:
以升序为例,该需求中rate字段为varcahr类型,因此直接排序会出现“1%->10%->11%->2%->3%”的情况,显然不是我们想要的结果。
所以我们需要对该列数据查询时进行数据类型转换,转换成 number 类型;在oracle中提供了两个将字符串类型转换为数字类型的方式:
1、TO_NUMBER(COLUMN) 将某一列转换为数字类型。
2、CAST(COLUMN AS NUMBER(10,2)) 将某一列转换为其他类型,此处为数字,只要条件满足可以转换为其他任意类型。
不过,经过测试,这样直接进行数据类型转换后排序,是不可行的,会报错:该列不是有效的数字,什么原因呢?是因为,rate列中存在“%”,“xx%”不是有效的数字,不能直接转换为number类型。
此时,我们只需要将末尾的“%”去除就得到可以转换为number类型的数字,也就我们要截取字符串,将“%”前面的数据截取出来。而在oracle中提供了 substr 方法用来截取字符串:
语法:
substr( string, start_position, [ length ] )
其中string为字符串,start_position为起始位置,length为截取长度;
其中start_position为负数的时起始位置从字符串末尾开始算起。 length可省略,而length省略时返回start_position位置后面的所有字符
看到这里,就发现 substr 方法中只能往后截取,而不能从后往前截取。另外,我们需要的是“%”前面的所有字符的,但其长度是未知的,因此就用到了另外一个方法instr,instr方法会返回指定字符出现的位置。即指定字符查找:
语法:
instr(string1,string2[,start_position[,nth_appearence]])
string1:要在此字符串中查找。
string2:要在string1中查找的字符串。
start_position:从string1开始查找的位置。可选,默认为1,正数时,从左到右检索,负数时,从右到左检索。(此处与substr相同,即为负的时候只是起始位置从右开始算)
nth_appearence:查找第几次出现string2。可选,默认为1,不能为负。
这样,我们可以使用instr查找“%”出现的位置,也就是该列数据的最后一个字符位置索引,用索引减1,得到该列数据去除百分号后的字符长度,也就是我们需要截取字符串的长度,截取的字符串为:substr(rate, 0,instr(rate,'%')-1),然后将它转化为number类型,并排序就OK了!
最后我们得到sql语句:
select * from profit order by CAST(substr(rate , 0,instr(rate ,'%')-1) AS number(10,2))或
select * from profit order by to_number(substr(rate , 0,instr(rate ,'%')-1))
总结:
实际开发中这样的情况比较少,因为“%”这个东西,可以直接在前端加的,数据库里面只需要存储number类型的数据就可了。但也存在其他类似的情况,例如:某公司的员工编号:序号+M,序号+MX。。。类似的情况还是有的。
另外,如果字母在前面那么的话更为简单,因为只需要从字母后一位开始,截取字母后面的所有就可以直接转换类型排序了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。